# -*- coding: utf-8 -*-
"""
Created on Fri Jul 27 21:40:50 2018

@author: Zhang Yafei
"""
"""
功能： 求一个序列或者多个序列进行函数映射之后的值，就该想到map这个函数，它是python自带的函数，在python3.*之后返回的是迭代器，同filter，需要进行列表转换 
调用： map(function,iterable1,iterable2)，function中的参数值不一定是一个x，也可以是x和y，甚至多个；后面的iterable表示需要参与function运算中的参数值，有几个参数值就传入几个iterable 
map函数的原型是map(function, iterable, …)，它的返回结果是一个列表。
参数function传的是一个函数名，可以是python内置的，也可以是自定义的。 
参数iterable传的是一个可以迭代的对象，例如列表，元组，字符串这样的。
这个函数的意思就是将function应用于iterable的每一个元素，结果以列表的形式返回。
注意到没有，iterable后面还有省略号，意思就是可以传很多个iterable，如果有额外的
iterable参数，并行的从这些参数中取元素，并调用function。如果一个iterable参数比
另外的iterable参数要短，将以None扩展该参数元素。
map()函数接收两个参数，一个是函数，一个是序列，map将传入的函数依次
作用到序列的每个元素，并把结果作为新的list返回。
"""


# 1.map自定义函数
def f(x):
    return x * x


a = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
list(a)
# 2.map复杂函数
l1 = list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9]))
l2 = [str(x) for x in [1, 2, 3, 4, 5, 6, 7, 8, 9]]


# 3.实例
def add(x, y, z):
    return x, y, z


list1 = [1, 2, 3]
list2 = [1, 2, 3, 4]
list3 = [1, 2, 3, 4, 5]
list4 = [1, 2, 3, 4, 5, 6]
res = map(add, list1, list2, list3)
list(res)


def add(x, y, z):
    return x + y + z


list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = [1, 2, 3]
list(map(add, list1, list2, list3))

func = lambda x, y, z: x + y + z
func(list1, list2, list3)


def format_name(s):
    return s.capitalize()


list(map(lambda x: x.capitalize(), ['adam', 'LISA', 'barT']))

foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]

list(map(lambda x: x * 2 + 10, foo))
print([x * 2 + 10 for x in foo])

"""
功能： filter的功能是过滤掉序列中不符合函数条件的元素，当序列中要删减的元素可以用某些函数描述时，就应该想起filter函数。 
调用： filter（function，sequence），function可以是匿名函数或者自定义函数，它会对后面的sequence序列的每个元素判定是否符合函数条件，返回TRUE或者FALSE，从而只留下TRUE的元素；sequence可以是列表、元组或者字符串 
Python内建的filter()函数用于过滤序列。
和map()类似，filter()也接收一个函数和一个序列。和map()不同的时，filter()把传入的函数依次作用于每个元素，
然后根据返回值是True还是False决定保留还是丢弃该元素。
"""


# 例1，在一个list中，删掉偶数，只保留奇数，可以这么写：
def is_old(x):
    return x % 2 == 0


list(filter(is_old, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
print([x for x in foo if x % 3 == 0])

# 例2：在一个list中，只保留能被三整除的数字
print(list(filter(lambda x: x % 3 == 0, foo)))
print([x for x in foo if x % 3 == 0])

"""
描述
功能： 对一个序列进行压缩运算，得到一个值。但是reduce在python2的时候是内置函数，到了python3移到了functools模块，所以使用之前需要 from functools import reduce 
调用： reduce（function，iterable），其中function必须传入两个参数，iterable可以是列表或者元组 
reduce() 函数会对参数序列中元素进行累积。
函数将一个数据集合（链表，元组等）中的所有数据进行下列操作：用传给 reduce 中的函数
function（有两个参数）先对集合中的第 1、2 个元素进行操作，得到的结果再与第三个数
据用 function 函数运算，最后得到一个结果。
reduce(function, iterable[, initializer])
function -- 函数，有两个参数
iterable -- 可迭代对象
initializer -- 可选，初始参数
"""
from functools import reduce

print(reduce(lambda x, y: x + y, foo))


def char2num(s):
    return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[s]


def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))


print(str2int('12345'))


def kfactorial(k):
    """求k的阶乘"""
    if k == 0 or k == 1:
        return 1
    from functools import reduce
    return reduce(lambda x, y: x * y, list(range(1, k + 1)))


def kfactorial2(k):
    a = 1
    for i in range(1, k + 1):
        a *= i
    return a


def kfactorial3(k):
    if k == 0 or k == 1:
        return 1
    else:
        return kfactorial3(k - 1)


kfactorial(5)
kfactorial2(6)
kfactorial3(7)
